/*
 * File Name     : @(#)Dispatcher.java
 * Creation Date : Jul 20, 2009
 * Author        : Anirudh Vyas
 * 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package hcis.service.def.impl;

import hcis.context.event.listener.context.def.impl.BusinessEventListenerContext;
import hcis.context.event.listener.context.def.impl.DAOEventListenerContext;
import hcis.core.engine.def.impl.Engine;
import hcis.core.engine.driver.def.impl.Driver;
import hcis.dto.broadcast.agent.def.impl.BroadcastingAgent;
import hcis.dto.event.IEvent;
import hcis.dto.event.IEvent.EventType;
import hcis.dto.event.def.impl.CreateEvent;
import hcis.dto.event.listener.def.impl.CreateDefaultModelEventBusinessListener;
import hcis.dto.event.listener.def.impl.CreateDefaultModelEventDAOListener;
import hcis.model.def.impl.DefaultModel;
import hcis.service.IDispatcher;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;

import javax.jws.WebService;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * Core event dispatcher that engages the engine by passing in events and grabbing the processed results from the same.
 * 
 * @author rudra
 */
@WebService(endpointInterface = "hcis.service.IDispatcher")
public final class Dispatcher implements IDispatcher {

	/**
	 * {@inheritDoc}
	 */
	public final String dispatch(final String xmlEventDispatch) {
		try {
			final Random random = new Random(10001L);
			final File file = new File("event-source" + random.nextLong() + ".xml");
			final boolean wasFileCreated = file.createNewFile();
			if (!wasFileCreated) {
				return "FAILURE";

			}
			final FileWriter fw = new FileWriter(file);
			fw.write(xmlEventDispatch);
			fw.flush();
			fw.close();
			final DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			final Document document = db.parse(file);
			file.delete();
			final IEvent<DefaultModel> event = populateEventModel(document);
			final BroadcastingAgent<DefaultModel> broadcastingAgent = new BroadcastingAgent<DefaultModel>();
			final Driver driver = new Driver();
			final BusinessEventListenerContext bizContext = new BusinessEventListenerContext() {
				private static final long serialVersionUID = 1L;

				/**
				 * {@inheritDoc}
				 */
				@Override
				public void load() {
					super.load();
					getEventListenerMappings().put(EventType.CREATE, CreateDefaultModelEventBusinessListener.class);
				}
			};
			final DAOEventListenerContext daoContext = new DAOEventListenerContext() {
				private static final long serialVersionUID = 1L;

				/**
				 * {@inheritDoc}
				 */
				@Override
				public void load() {
					super.load();
					getEventListenerMappings().put(EventType.CREATE, CreateDefaultModelEventDAOListener.class);
				}
			};
			driver.setBizContext(bizContext);
			driver.setDaoContext(daoContext);
			final Engine engine = new Engine(bizContext, daoContext);
			driver.setEngine(engine);
			broadcastingAgent.setDriver(driver);
			broadcastingAgent.broadcast(event);
			// TODO : Ensure that result being set is a literal that can be used here ...
			// NOTE : Most likely a result should be JSON string ... let it be back and forth ... (XML is just a little hefty to deal with).
			return "{ result : " + event.getProcessedResult().getResult() + " }";
		} catch (final ParserConfigurationException e) {
			e.printStackTrace();
		} catch (final SAXException e) {
			e.printStackTrace();
		} catch (final IOException e) {
			e.printStackTrace();
		}
		return "SUCCESS";
	}

	/**
	 * Populates and gets event model by document provided.
	 * 
	 * @param document
	 *            DOM document.
	 */
	private final IEvent<DefaultModel> populateEventModel(final Document document) {
		final NodeList nodeList = document.getChildNodes();
		return new CreateEvent<DefaultModel>(new DefaultModel(1L));
	}
}
